
#include <functional>
#include <iostream>

#include <conio.h>

#include "glare.core.GpuResourceFactory.h"
#include "glare.core.RenderWindow.h"
#include "glare.core.DrawContext.h"

#include "glare.d3d11.Driver.h"
#include "glare.gles2.Driver.h"

#include "glare.core.ColourValue.h"
#include "glare.core.StringConverter.h"
#include "glare.core.Win32Window.h"

using namespace Glare;

/** Creates a RenderWindow and initializes it */
RenderWindow* CreateRenderWindow(Driver* driver, HINSTANCE hinstance, const string& window_class, const string& window_title)
{
	Win32WindowConstructionParams* w32_params = new Win32WindowConstructionParams();
	w32_params->InstanceHandle = (uint)hinstance;
	w32_params->Class = window_class;
	w32_params->Title = window_title;

	PlatformWindow* platform_window = PlatformWindow::CreateDefaultWindow(800, 600, w32_params);
	RenderWindow* render_window = driver->CreateRenderWindow(platform_window);

	render_window->Initialize();

	return render_window;
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);
	MSG msg = {0};

	const int num_windows = 3;
	Driver* driver;
	RenderWindow* render_windows[num_windows];
	ColourValue clear_colors[num_windows] = 
	{
		ColourValue::Red,
		ColourValue::Green,
		ColourValue::Blue
	};

	string names[num_windows] = 
	{
		"RED",
		"GREEN",
		"BLUE"
	};

	try
	{
		driver = new D3D11Driver();
		//driver = new GLES2Driver();

		for (int i = 0; i < num_windows; ++i)
		{
			string cls = "wnd_class_" + StringConverter::ToString(i);

			auto render_window = CreateRenderWindow(driver, hInstance, cls, "Demo.03.HelloMultiWindow " + names[i]);
			render_window->SetPresentSyncInterval(1);
			render_windows[i] = render_window;
		}

		auto immediate_context = driver->GetImmediateDrawContext();

		// Main message loop
		while (msg.message != WM_QUIT)
		{
			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else
			{
				for (int i = 0; i < num_windows; ++i)
				{
					RenderWindow* render_window = render_windows[i];
					const ColourValue& clear_color = clear_colors[i];

					immediate_context->OM_SetRenderTarget(render_window, NULL);
					immediate_context->ClearRenderTarget(render_window, clear_color);

					render_window->Present();
				}
			}
		}
	}
	catch (Exception e)
	{
		MessageBox(0, e.what(), 0, 0);
	}

	delete driver;

	return (int)msg.wParam;
}
